var cmsService = angular.module('CmsServices', ['ngResource']);

/**
 * constant和value主要就是用于存放一些数据或方法以供使用, 区别是constant一般是存放固定内容,value存放可能会被修改的内容
 *
 * value可以被修饰：
 * app.config(function($provide){
    $provide.decorator("myConfig",function($delegate){
      $delegate.money = "100w";
      return $delegate
    })
   });
 */
cmsService.constant("Config", {
  env:'pro',  //dev, pro
  profiles:{
    dev:{
      context: 'http://xiaochaguan.yihuyixi.com/cms',
      psContext: 'http://xiaochaguan.yihuyixi.com/ps',
      wxCtx: 'http://xiaochaguan.yihuyixi.com/wxservice',
      seckillCtx: 'http://xiaochaguan.yihuyixi.com/goodsKill',
      scheduleCtx: 'http://xiaochaguan.yihuyixi.com/scheduler',
      auctionCtx: 'http://xiaochaguan.yihuyixi.com/cmsAuction',
      webspreadCtx: 'http://xiaochaguan.yihuyixi.com/webspread'
    },
    pro:{
      context: '/cms',
      psContext: '/ps',
      wxCtx: '/wxservice',
      seckillCtx: '/goodsKill',
      scheduleCtx: '/scheduler',
      auctionCtx: '/cmsAuction',
      webspreadCtx: '/webspread'
    }
  },
  enableH5: false,
  enableAuth: false,
  basedata: {
    artist: "cms/basedata/:type/artist",
    category: "cms/basedata/:type/type",
    subCategory: "cms/basedata/:type/type/:category",
    subject: "cms/basedata/:type/theme",
    scene: "cms/basedata/:type/scene",
    type: "cms/basedata",
    express: "cms/config/express"
  },
  authType: {
    navMenu: '1',
    module: '2',
    router: '3'
  },
  ssoInterval: 1700000,
  autoSaveInterval: 30000,
  autoLoginDuration: 60*60*1000,
  userProfile:{
    portrait: ""
  },
  i18n:'zh-cn'
})

/**
 * 事件类型
 * @type {String}
 */
.constant('AUTH_EVENTS', {
  loginSuccess: 'auth-login-success',
  loginFailed: 'auth-login-failed',
  sessionTimeout: 'auth-session-timeout',
  notAuthenticated: 'auth-not-authenticated',
  notAuthorized: 'auth-not-authorized',
  routerFailed: 'router-failed',
  pageNotFound: 'page-not-found',
  internalError:'internal-error'
})
/**
 * 用户角色
 * @type {String}
 */
.constant('USER_ROLES', {
  all: '*',
  admin: 'administrator',
  normal: 'normal',
  guest: 'guest'
})

/** 通用存储 */
.service("Store", ['Config', function(Config){
  this.save = function(key, value, expires){
    if(Config.enableH5 && window.localStorage){
      window.localStorage.setItem(key, value);
    }else{
      Yihu.Cookie.add(key, value, expires);
    }
  };

  this.setExpires = function(key, expires){
    if(expires){
      var val = this.get(key);
      this.save(key, val, expires);
    }
  };

  this.get = function(key){
    if(Config.enableH5 && window.localStorage){
      return window.localStorage.getItem(key);
    }else{
      return Yihu.Cookie.get(key);
    }
  };

  this.localSave = function(key, value) {
    if (window.localStorage) {
      window.localStorage.setItem(key, value);
    } else {
      Yihu.Cookie.add(key, value, 24*3600000);
    }
  };

  this.localGet = function(key) {
    if(window.localStorage){
      return window.localStorage.getItem(key);
    } else {
      return Yihu.Cookie.get(key);
    }
  };

  this.localRemove = function(key) {
    if(window.localStorage){
      return window.localStorage.removeItem(key);
    } else {
      return Yihu.Cookie.remove(key);
    }
  };

  this.getUnsaved = function(module, id){
    var autoKey = "autosave-"+module+(id || '');

    if(Config.enableH5 && window.localStorage){
      return localStorage.getItem(autoKey);
    }else{
      return Yihu.Cookie.get(autoKey);
    }
  };

  this.remove = function(key){
    if(Config.enableH5 && window.localStorage){
      window.localStorage.removeItem(key);
    }else{
      Yihu.Cookie.remove(key);
    }
  };

  this.merge = function(key, value, expires){
    if(Config.enableH5 && window.localStorage){
      var oldValue = window.localStorage.getItem(key);
      if(oldValue && oldValue != value){
        value = oldValue + value;
      }
      window.localStorage.setItem(key, value);
    }else{
      var oldCookieValue = Yihu.Cookie.get(key);
      if(oldCookieValue && oldCookieValue != value){
        value = oldCookieValue + value;
      }
      Yihu.Cookie.add(key, value, expires);
    }
  };
}])

/**
 * 用户会话对象
 */
.service('Session', ['$cookieStore', 'Store', 'Config', function ($cookieStore, Store, Config) {
  this.create = function (user) {
    this.user = user;
    // $cookieStore.put("user", user);
    Store.save("user", JSON.stringify(user), Config.autoLoginDuration || (24*3600000));
    Store.save("loginToken", user.userName + user.userId, (1*3600000));
  };
  
  this.destroy = function () {
    $cookieStore.remove("user");
    $cookieStore.remove("loginToken");
    this.user = null;
  };

  this.getUser = function(){
    var user = this.user;
    if(!user){
      user = $cookieStore.get("user");
      this.user = user;
    }
    return user;
  };

  return this;
}])

/**
 * 身份认证和鉴权服务
 */
.factory("AuthService", ['$http', 'Session', 'Config', '$q', 'UserService', '$rootScope', function($http, Session, Config, $q, UserService, $rootScope){
  var authService = {};

  authService.login = function(credential){
    var ctx = Config.profiles[Config.env].context + '/user';
    var psDownloadCtx = Config.profiles[Config.env].psContext + '/download/';
    var ticket = {};
    ticket.userName = credential.userName;
    ticket.remember = credential.remember;
    if(credential && credential.password){
      ticket.password = md5(credential.password);
    }
    return $http.post(ctx + '/login', ticket).then(function(res){
      var data = res.data;
      var user = {
        userId: data.userId,
        userName: credential.userName,
        role: data.roleCode,
        icon: data.icon ? psDownloadCtx+data.icon : ''
      };
      if (data.icon) {
        data.icon = psDownloadCtx+data.icon;
      } else {
        data.icon = '';
      }
      Session.create(data);
      return user;
    });
  };

  authService.logOff = function(userId){
    var ctx = Config.profiles[Config.env].context + '/user';
    var deffered = $q.defer();
    $http.get(ctx + '/logout/' + userId).then(function(res){
      var data = res.data;
      if(data.result === 0){
        Session.destroy();
        deffered.resolve("用户已注销成功！");
      }else{
        deffered.reject("用户注销失败，请稍候重试！");
      }
    });
    return deffered.promise;
  };

  authService.isAuthenticated = function(){
    var user = Session.user;
    if(!user){
      return false;
    }
    return !!user.userId;
  };

  // authService.isAuthorized = function(authorizedRoles){ 
  //   if(!angular.isArray(authorizedRoles)){
  //     authorizedRoles = [authorizedRoles];
  //   }

  //   //Any role can be access.
  //   if(authorizedRoles.indexOf('*') != -1){
  //     return true;
  //   }

  //   if(!(Session.user && Session.user.role)){
  //     return false;
  //   }
  //   return (authService.isAuthenticated() && authorizedRoles.indexOf(Session.user.role) !== -1);
  // };
  
  /**
   * 用户鉴权
   * @param  {Function} next            UI-router路由规则
   * @param  {[type]}   userPriviledges 当前登录用户权限列表
   * @return {Boolean}                  返回鉴权结果promise对象
   */
  authService.isAuthorized = function(next, userPriviledges){
    var deffered = $q.defer();
    var user = Session.user;
    if(!user || !user.userId){
      deffered.reject(false);
    }

    if(!next || !next.url){
      deffered.reject(false);
    }

    var flag = false;
    if(userPriviledges.length===0){
      var ctx = Config.profiles[Config.env].context + '/user';
      $http.get(ctx + '/getPriviledge?userId='+ user.userId).then(function(res){
        userPriviledges = $rootScope.userPriviledges = res.data || [];

        for(var i=0; i<userPriviledges.length; i++){
          var uri = userPriviledges[i].resourceURI;
          if(Config.authType.router===userPriviledges[i].resourceType && next.name === uri){
            flag = true;
            deffered.resolve(true);
          }else if(uri && next.url.indexOf(uri) >= 0){
            flag = true;
            deffered.resolve(true);
          }
        }

        if(!flag){
          deffered.reject(false);
        }
      });
    }else{
      for(var i=0; i<userPriviledges.length; i++){
        var uri = userPriviledges[i].resourceURI;         
        if(Config.authType.router===userPriviledges[i].resourceType && next.name === uri){
          flag = true;
          deffered.resolve(true);
        }else if(uri && next.url.indexOf(uri) >= 0){
          flag = true;
          deffered.resolve(true);
        }
      }
      
      if(!flag){
        deffered.reject(false);
      }
    }
    return deffered.promise;
  };

  return authService;
}])
/**
 * HTTP请求拦截器
 *
 * 401 Unauthorized — The user is not logged in
   403 Forbidden — The user is logged in but isn’t allowed access
   419 Authentication Timeout (non standard) — Session has expired
   440 Login Timeout (Microsoft only) — Session has expired
 */
.factory("AuthInterceptor", ['$rootScope', '$q', 'AUTH_EVENTS', function($rootScope, $q, AUTH_EVENTS){
  return {
    responseError: function(response){
      $rootScope.$broadcast({
        401: AUTH_EVENTS.notAuthenticated,
        403: AUTH_EVENTS.notAuthorized,
        419: AUTH_EVENTS.sessionTimeout,
        440: AUTH_EVENTS.sessionTimeout,
        405: AUTH_EVENTS.routerFailed,
        404: AUTH_EVENTS.pageNotFound
        // ,500: AUTH_EVENTS.internalError
      }[response.status], response);

      return $q.reject(response);
    }
  };

}]);

/**
 * 基础服务
 */
cmsService.factory('BasicService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context;
  return $resource('/api', {}, {
    //获取导航列表
    getNav:{
      url: 'javascripts/nav.json',
      method:'GET',
      cache:true,
      isArray:true
    },

    //获取商品类型列表
    getProductTypes:{
      url: ctx + '/datadic/childrens?parentPath=' + Config.basedata.type,
      method:'GET',
      cache:true
    },

    //获取类别列表
    getArtworkCategory:{
      url: ctx+'/datadic/childrens?parentPath=' + Config.basedata.category,
      method:'GET',
      cache:true
    },

    //获取子类别列表
    getArtworkSubCategory:{
      url: ctx+'/datadic/childrens?parentPath=' + Config.basedata.subCategory,
      method:'GET',
      cache:true
    },

    //获取主题列表
    getArtworkTheme:{
      url: ctx+'/datadic/childrens?parentPath=' + Config.basedata.subject,
      method:'GET',
      cache:true
    },

    //获取场景列表
    getArtworkScene:{
      url: ctx+'/datadic/childrens?parentPath=' + Config.basedata.scene,
      method:'GET',
      cache:true
    },

    //获取艺术家列表(deprecated)
    getArtworkAuthor:{
      url: ctx+'/artworkAuthor/listAll',
      method:'GET',
      cache:true
    }, 

    //获取艺术家列表
    getArtist: {
      url: ctx+'/datadic/childrens?parentPath=' + Config.basedata.artist,
      method:'GET',
      cache:true
    },

    //获取类型列表（deprecated）
    // getArtworkType:{
    //   url: ctx+'/artworkType/listAll',
    //   method:'GET',
    //   cache:true
    // }, 

    //获取商品分类列表
    getArtworkType:{
      url: ctx + '/datadic/childrens?parentPath=' + Config.basedata.type,
      method:'GET',
      cache:true
    }, 

    //获取状态列表
    getCommodityStates:{
      url: ctx+'/commodityStates/listAll',
      method:'GET',
      cache:true
    },

    //获取衍生品分类列表
    getDerivativesCategories:{
      url: ctx+'/derivativesCategory/listAll',
      method:'GET',
      cache:true
    }, 

    //获取材质列表
    getMaterialList:{
      url: ctx+'/material/listAll',
      method:'GET',
      cache:true
    },

    //自动保存
    autoSaving:{
      url: ctx + '/article/autoSave',
      method: 'POST', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }      
    },

    //获取上次保存内容
    getUnsaved: {
      url: ctx + '/article/getAutoContent',
      method: 'POST', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //获取快递列表
    getExpressList:{
      url: ctx+'/datadic/childrens?parentPath=' + Config.basedata.express,
      method:'GET',
      cache:true
    }

  });
});

/**
 * 艺术品服务
 */
cmsService.factory('ArtworkService', function($resource, Config){
  var artworkUrl = Config.profiles[Config.env].context + '/artwork';
  return $resource(artworkUrl, {}, {
    //获取艺术品分页列表
    getList:{
      url: artworkUrl+'/list',
      method:'GET', 
      params:{}
    }, 

    //查询单个产品信息
    findOne:{
      url: artworkUrl + '/:id',
      method:'GET'
    }, 

    //新增艺术品
    create:{
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新艺术品信息
    update:{
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除艺术品
    remove:{
      url: artworkUrl + '/:id',
      method:'DELETE'
    },

    //缓存首页redis缓存
    refreshCache:{
      url: artworkUrl + '/home',
      method:'GET',
      cache: false
    }

  });
});


/**
 * 微信服务
 */
cmsService.factory('WeixinService', function($resource, Config){
  var ctx = Config.profiles[Config.env].wxCtx;
  return $resource(ctx, {}, {
    arrivalNotify:{
      url: ctx + '/attention',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }

  });
});


/**
 * 衍生品服务
 */
cmsService.factory('DerivativiesService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/derivatives';
  return $resource(ctx, {}, {
    //获取衍生品分页列表
    getList:{
      url: ctx+'/list',
      method:'POST', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      params:{
        curPage:'@pageNumber', 
        pageSize:'@pageSize'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    //查询单个产品信息
    findOne:{
      url: ctx + '/:id',
      method:'GET'
    }, 

    //新增衍生品
    create:{
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新衍生品信息
    update:{
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除衍生品
    remove:{
      url: ctx + '/:id',
      method:'DELETE'
    }

  });
});

/**
 * 产品款式服务
 */
cmsService.factory('ProductModelsService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/artworkModel';
  return $resource(ctx, {}, {
    //获取衍生品分页列表
    getList:{
      url: ctx+'/list',
      method:'GET', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      params:{},
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    //查询单个信息
    findOne:{
      url: ctx + '/:id',
      method:'GET'
    }, 

    //新增
    create:{
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url: ctx + '/:id',
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url: ctx + '/:id',
      method:'DELETE'
    }

  });
});

/**
 * 文章管理服务
 */
cmsService.factory('ArticleService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/article';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'GET', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/:id'
    }, 

    //新增
    create:{
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url:ctx +'/:id',
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/:id',
      method:'DELETE'
    }

  });
});

/**
 * 分类管理服务
 */
cmsService.factory('CategoryService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/articleCategory';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'POST', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/:id'
    }, 

    //新增
    create:{
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url:ctx +'/:id',
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/:id',
      method:'DELETE'
    }

  });
});

/**
 * 标签管理服务
 */
cmsService.factory('TagService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/tagsmanger';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'GET', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      params:{
        userName: '@userName',
        tagsName: '@tagsName'
      },
      isArray:true
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/:id'
    }, 


    //新增
    create:{
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx,
      method:'DELETE', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      params:{
        id: '@id'
      }
    }

  });
});

/**
 * 用户管理服务
 */
cmsService.factory('UserService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/user';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'GET', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      params:{
      }
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/:id'
    }, 

    //新增
    create:{
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url:ctx +'/:id',
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/:id',
      method:'DELETE'
    },

    //修改密码
    changePwd:{
      url: ctx + '/changePassword',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //刷新SSO过期时间
    refreshSSO: {
      url: ctx + '/isValid/:userId',
      method:'GET'
    },

    //获取用户的权限列表
    getUserPriviledge: {
      url: ctx + '/getPriviledge',
      method: 'GET',
      params:{
        userId: '@userId'
      }
    },

    setAgentLevel:{
      url: ctx + '/setAgentLevel',
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    setUserLevel:{
      url: ctx + '/setUserLevel',
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }

  });
});

/**
 * 用户组管理服务
 */
cmsService.factory('UserGroupService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/user/group';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'GET', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/:id'
    }, 

    //新增
    create:{
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url:ctx +'/:id',
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/:id',
      method:'DELETE'
    },

    //查询用户组的用户列表
    getUsers:{
      url: ctx + '/users',
      method: 'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //分配用户组
    assign:{
      url: ctx + '/assignUsers',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }

  });
});

/**
 * 用户角色管理服务
 */
cmsService.factory('UserRoleService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/user/role';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'GET',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/:id'
    }, 

    //新增
    create:{
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url:ctx +'/:id',
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/:id',
      method:'DELETE'
    },

    //分配用户组
    assignGroups:{
      url: ctx + '/assignGroups',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //分配权限
    assignPermits:{
      url: ctx + '/assignPermits',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //查询角色中的用户组列表
    getRoleGroups:{
      method:'POST',
      url:ctx +'/groups',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    getPriviledge:{
      url: ctx + '/priviledges',
      method: 'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      },
      isArray:true
    }
  });
});


/**
 * 用户权限管理服务
 */
cmsService.factory('PermissionService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/user/priviledge';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'GET',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/:id'
    }, 

    //新增
    create:{
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url:ctx +'/:id',
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/:id',
      method:'DELETE'
    },

    //分配资源
    assignResources:{
      url: ctx + '/assignResources',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //获取当前权限的所有资源
    getResources:{
      url: ctx + '/resources/:id',
      method: 'GET',
      isArray: true 
    },

    //获取当前节点的所有父权限，用于导航条
    getParentPermits:{
      url: Config.profiles[Config.env].context + '/user/priviledges/parent/:id',
      method: 'GET',
      isArray:true
    },

    //获取当前节点的所有子级权限
    getChildren:{
      url: ctx + '/childrens/:id',
      method: 'GET',
      isArray: true
    }

  });
});

/**
 * 用户资源管理服务
 */
cmsService.factory('ResoucesService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/user/resource';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/:id'
    }, 

    //新增
    create:{
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url:ctx +'/:id',
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/:id',
      method:'DELETE'
    }
    
  });
});

/**
 * 数据字典管理服务 
 */
cmsService.factory('DataDictService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context +'/datadic';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'GET', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/:id'
    }, 

    //新增
    create:{
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url:ctx +'/:id',
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/:id',
      method:'DELETE'
    },

    //获取当前分类所有的父分类导航
    getParents: {
      url:ctx + '/parents/:id',
      method: 'GET',
      isArray: true
    },

    //获取当前分类下的所有的子级节点
    getChildren: {
      url:ctx + '/childrens',
      method: 'GET',
      cache: true
    }

  });
});

/**
 * 富文本编辑器服务
 */
cmsService.factory('RichTextService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context;

  return $resource(ctx, {}, {
    uploadCallback:{
      url: ctx + '/richText/upload',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {   
        return JSON.stringify(obj);        
      }
    }
  });

});

/**
 * 文件管理服务
 */
cmsService.factory('FileManagerService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/filemanger';
  return $resource(ctx, {}, {
    getList:{
      url: ctx + '/list',
      method:'GET',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      params:{
        path:'@path',
        order:'@order',
        type:'@type',
        tag:'@tag',
        desc:'@desc',
        startDate:'@startDate',
        endDate:'@endDate'
      }
    }, 

    dirTree:{
      url: ctx + '/allDirectory',
      method:'GET',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      }
    },

    //新建文件夹
    mkdir:{
      url: ctx + '/create',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    //重命名
    rename:{
      url: ctx + '/rename',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除文件或文件夹
    remove:{
      url: ctx + '/delete',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //复制到
    copy:{
      url: ctx + '/copy',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //移动到
    move:{
      url: ctx + '/move',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }

  });
});

/** 
 * 轮播广告管理
 */
cmsService.factory('PosterService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/poster';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'GET', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/:id'
    }, 

    //新增
    create:{
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url:ctx +'/:id',
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/:id',
      method:'DELETE'
    }

  });
});

/** 
 * 评论管理
 */
cmsService.factory('CommentService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/comment';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'GET', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/:id'
    }, 

    //新增
    create:{
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //审批
    approve:{
      url:ctx +'/audit',
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/:id',
      method:'DELETE'
    }

  });
});

/**
 主题活动管理服务
 */
cmsService.factory('ActivityService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/activity';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'GET',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/:id'
    }, 

    //新增
    create:{
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url:ctx +'/:id',
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/:id',
      method:'DELETE'
    }
  });

});

/**
 * 订单管理服务
 */
cmsService.factory('OrderService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context +'/order', wxCtx = Config.profiles[Config.env].wxCtx;
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'GET', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      params:{
      }
    }, 

    //获取分页列表
    getDeliveryLog:{
      url:Config.profiles[Config.env].context +'/deliverlog/list',
      method:'GET', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      }
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/:id'
    }, 

    //新增
    create:{
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx,
      method:'DELETE', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      params:{
        id: '@id'
      }
    },

    //更新价格
    updatePrice:{
      url: ctx + '/changePrice',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //发货
    deliveryGoods:{
      url: ctx + '/deliver',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //延迟发货提醒
    orderDelay:{
      url: wxCtx + '/orderDelay',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //订单受理提醒
    annouceOrderMsg:{
      url: wxCtx + '/orderAccept',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //物流跟踪
    trackExpress:{
      url: wxCtx + '/order/express',
      method:'GET',
      cache: true
    },

    //退款审核
    refund:{
      url: ctx + '/sys/refund',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //退款审核
    rejectRefund:{
      url: ctx + '/sys/cancelRefund',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //现场自提，直接关单
    closeOrder:{
      url: ctx + '/finish',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }
  });

});

/**
 秒杀管理服务
 */
cmsService.factory('SeckillService', function($resource, Config){
  var ctx = Config.profiles[Config.env].seckillCtx + '/seckill';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'GET',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //获取秒杀成功列表
    getSuccessKilledList:{
      url: ctx +'/successkilled/list',
      method:'GET',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/:id/detail'
    }, 

    //新增
    create:{
      method:'POST',
      url: ctx + '/create',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url:ctx +'/:id/update',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/:id/delete',
      method:'GET'
    }, 

    //启动秒杀定时任务
    startupSeckillTask:{
      method:'POST',
      url: Config.profiles[Config.env].scheduleCtx + '/wx/attention',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }    
  });

});


/**
 拍卖管理服务
 */
cmsService.factory('AuctionService', function($resource, Config){
  var ctx = Config.profiles[Config.env].auctionCtx;
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/auctionList',
      method:'GET',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //获取拍卖出价列表
    getPricingList:{
      url: ctx +'/auctionProductPriceRecordList',
      method:'GET'
    },

    addPricing:{
      url: ctx +'/auctionProductPriceRecord',
      method:'GET',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    findOne:{
      method:'GET',
      url:ctx +'/auction/:id'
    }, 

    //新增
    create:{
      method:'POST',
      url: ctx + '/auction',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url:ctx +'/auction',
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/auction/:id',
      method:'DELETE'
    }, 

    //启动定时任务
    startupTask:{
      method:'POST',
      url: Config.profiles[Config.env].scheduleCtx + '/wx/attention',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }

  });

});


/** 
 * 二维码活动管理
 */
cmsService.factory('CouponService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/qrcode';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'GET', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/:id'
    }, 

    //新增
    create:{
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url:ctx +'/:id',
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/:id',
      method:'DELETE'
    }, 

    download:{
      method:'GET',
      url:ctx +'/download/:id'
    },

    //生成产品对应的二维码
    generateQrcode: {
      url: ctx + '/group2',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //创建群组活动
    createGroupCoupon:{
      url: ctx + '/group1',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //添加用户组成员
    addGroupMember:{
      url: ctx + '/publishids',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }

  });
});

/** 
 * 二维码活动管理
 */
cmsService.factory('CouponService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/qrcode';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'GET', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    getCoupons:{
      url: Config.profiles[Config.env].context + '/coupon/list',
      method:'GET', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      },
      isArray: true
    },

    findOne:{
      method:'GET',
      url:ctx +'/:id'
    }, 

    //新增
    create:{
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url:ctx +'/:id',
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/:id',
      method:'DELETE'
    }, 

    download:{
      method:'GET',
      url:ctx +'/download/:id'
    },

    //生成产品对应的二维码
    generateQrcode: {
      url: ctx + '/group2',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //创建群组活动
    createGroupCoupon:{
      url: ctx + '/group1',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //添加用户组成员
    addGroupMember:{
      url: ctx + '/publishids',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }

  });
});

/** 
 * 团购管理
 */
cmsService.factory('GroupBuyService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/groupBuy';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'GET', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/:id'
    }, 

    //新增
    create:{
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url:ctx +'/:id',
      method:'PUT',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/:id',
      method:'DELETE'
    }

  });
});

/** 
 * 首单特惠管理, 分享特惠，拼团管理
 */
cmsService.factory('FirstpayService', function($resource, Config){
  var ctx = Config.profiles[Config.env].webspreadCtx + '/specialfield';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'GET', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/get/:id'
    }, 

    //新增
    create:{
      method:'POST',
      url:ctx +'/add',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url:ctx +'/update',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/delete/:id',
      method:'DELETE'
    }

  });
});

/** 
 * 栏目管理
 */
cmsService.factory('ChannelService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/channel';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'GET', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/:id'
    }, 

    //新增
    create:{
      method:'POST',
      url:ctx,
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url:ctx +'/update',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/:id',
      method:'DELETE'
    }

  });
});

/** 
 * 栏目商品管理
 */
cmsService.factory('ChannelGoodsService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/channelGoods';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'GET', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/:id'
    }, 

    //批量新增多个商品
    batchInsert:{
      method:'POST',
      url:ctx +'/list',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    //新增
    create:{
      method:'POST',
      url:ctx,
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url:ctx +'/update',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/:id',
      method:'DELETE'
    }

  });
});

/** 
 * 进销存商品管理
 */
cmsService.factory('InventoryService', function($resource, Config){
  var ctx = Config.profiles[Config.env].context + '/stocksale/goods';
  return $resource(ctx, {}, {
    //获取分页列表
    getList:{
      url:ctx +'/list',
      method:'GET', 
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    }, 

    findOne:{
      method:'GET',
      url:ctx +'/:id'
    }, 

    //新增
    create:{
      method:'POST',
      url:ctx,
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //更新信息
    update:{
      url:ctx +'/update',
      method:'POST',
      headers:{
        'X-Requested-With':'XMLHttpRequest',
        'Content-Type': 'application/json;charset=UTF-8'
      },
      transformRequest: function(obj) {  
        return JSON.stringify(obj);  
      }
    },

    //删除
    remove:{
      url:ctx +'/:id',
      method:'DELETE'
    },

    //库存数据统计
    stat: {
      url: ctx + '/stat',
      method: 'GET'
    }

  });
});

/**
 * 模板动态加载器
 * 
 * @param  {[type]} $compile          [description]
 * @param  {[type]} $document         [description]
 * @param  {[type]} $controller       [description]
 * @param  {[type]} $http             [description]
 * @param  {[type]} $q                [description]
 * @param  {[type]} $rootScope        [description]
 * @return {[type]} $templateCache    [description]
 */
cmsService.factory('templateLoader', function($compile, $document, $controller, $http, $q, $rootScope, $templateCache){
  return {
    load: fetchTemplate,
    compile: loadAndCompile
  };

  function fetchTemplate(url) {
    return $http.get(url, {cache: $templateCache})
    .then(function (response) {
      return response.data && response.data.trim();
    });
  }

  function loadAndCompile(options) {
    var extend = angular.extend, 
    opts = extend({
      template: '',
      templateUrl: '',
      scope: null,
      controller: null,
      locals: {},
      appendTo: $document[0].body
    }, options || {});

    var templatePromise = opts.templateUrl ? this.load(opts.templateUrl) : $q.when(opts.template);

    return templatePromise.then(function (template) {
      var controller;
      var scope = opts.scope || $rootScope.$new();

      //Incase template doesn't have just one root element, do this
      var element = angular.element('<div>').html(template).contents();
      if (opts.controller) {
        controller = $controller(
          opts.controller,
          extend(opts.locals, {
            $scope: scope
          })
        );
        element.children().data('$ngControllerController', controller);
      }
      if (opts.appendTo) {
        angular.element(opts.appendTo).append(element);
      }
      $compile(element)(scope);

      return {
        element: element,
        scope: scope
      };
    });
  }
})

/**
 * 动态创建模态窗口
 * @return {[type]}                 [description]
 */
.factory('myModal', function (templateLoader) {
  function createModal(modal) {
    modal.hide = function(){
      console.log('modal.hide()');
    };

    modal.show = function(){
      console.log('modal.show()');
    };

    return modal;
  }

  return {
    loadTemplateUrl: function (url, options) {
      return templateLoader.compile({
        templateUrl: url,
        scope: options.scope
      }).then(function (modal) {
        return createModal(modal);
      });
    }
  };
});

/**
 * CMS模板功能（已支持缓存）
 */
angular.module("CmsTemplates", ["template/modal/dialog.html","template/modal/treeDialog.html", "template/modal/modal.html", "template/modal/imageDialog.html", "template/common/sidebar.html", "template/uploadTask.html", "template/modal/filesDialog.html"]);
//非模态框
angular.module("template/modal/dialog.html", []).run(function($templateCache) {
  $templateCache.put("template/modal/dialog.html",
    '<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">' + 
      '<div class="modal-dialog">' +
      '<div class="modal-content">' + 
         '<div class="modal-header">' + 
            '<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>' + 
            '<h4 class="modal-title" ng-bind="modal.title"></h4>' + 
         '</div>' + 
         '<div class="modal-body" ng-bind-html="modal.body | trustHtml"></div>' + 
         '<div class="modal-footer">' + 
            '<button type="button" class="btn btn-primary" ng-click="submitConfirm()" ng-bind="modal.buttons.YES"></button>' + 
            '<button type="button" class="btn btn-warning" data-dismiss="modal" ng-if="modal.buttons.NO" ng-bind="modal.buttons.NO"></button>' + 
         '</div>' + 
      '</div>' + 
  '</div>');
});

//树型对话框
angular.module("template/modal/treeDialog.html", []).run(function($templateCache) {
  $templateCache.put("template/modal/treeDialog.html",
    '<div class="modal fade" id="myDialog" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">' + 
      '<div class="modal-dialog">' +
      '<div class="modal-content">' + 
        '<div class="modal-header">' + 
          '<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>' + 
          '<h4 class="modal-title" ng-bind="dialog.title"></h4>' + 
       '</div>' + 
       // '<div class="modal-body" ng-bind-html="dialog.body | trustHtml"></div>' + 
       '<div class="modal-body"><tree-view tree-data="tree" text-field="name" value-field="id" item-clicked="itemClicked($item)" item-checked-changed="itemCheckedChanged($item)" can-checked="false"></tree-view></div>'+ 
       '<div class="modal-footer">' + 
          '<button type="button" class="btn btn-primary" ng-click="dialog.ok()" ng-bind="dialog.buttons.YES"></button>' + 
          '<button type="button" class="btn btn-warning" data-dismiss="modal" ng-if="dialog.buttons.NO" ng-bind="dialog.buttons.NO" ></button>' + 
        '</div>' + 
      '</div>' + 
  '</div>');
});

//模态框
angular.module("template/modal/modal.html", []).run(function($templateCache) {
  $templateCache.put("template/modal/modal.html",
    '<div class="modal fade modalDialog" tabindex="-1" role="dialog">' + 
      '<div class="modal-dialog">' +
      '<div class="modal-content">' + 
        '<div class="modal-header">' + 
          '<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>' + 
          '<h4 class="modal-title" ng-bind="dialog.title"></h4>' + 
        '</div>' + 
        '<div class="modal-body" ng-bind-html="dialog.body | trustHtml"></div>' + 
        '<div class="modal-footer">' + 
          '<button type="button" class="btn btn-primary" ng-click="dialog.ok()" ng-bind="dialog.buttons.YES"></button>' + 
          '<button type="button" class="btn btn-warning" data-dismiss="modal" ng-if="dialog.buttons.NO" ng-bind="dialog.buttons.NO" ></button>' + 
        '</div>' + 
      '</div>' + 
    '</div>');
});

//图片列表模态框
angular.module("template/modal/filesDialog.html", []).run(function($templateCache) {
  $templateCache.put("template/modal/filesDialog.html",
    '<div class="modal fade modalDialog" id="filesDialog" tabindex="-1" role="dialog">' + 
      '<div class="modal-dialog" style="width: 920px;">' +
      '<div class="modal-content">' + 
        '<div class="modal-header">' + 
          '<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>' + 
          '<h4 class="modal-title" ng-bind="dialog.title"></h4>' + 
        '</div>' + 
        '<div class="modal-body" style="_height: 450px; max-height: 450px; min-height: 182px; overflow-y: auto;"><filegrid></filegrid></div>' +
        '<div class="modal-footer">' + 
          '<button type="button" class="btn btn-primary" ng-click="dialog.goback()" ng-if="dialog.buttons.BACK" ng-bind="dialog.buttons.BACK"></button>' + 
          '<button type="button" class="btn btn-primary" ng-click="dialog.ok()" ng-bind="dialog.buttons.YES"></button>' + 
          '<button type="button" class="btn btn-warning" ng-click="dialog.discard()" data-dismiss="modal" ng-if="dialog.buttons.NO" ng-bind="dialog.buttons.NO" ></button>' + 
        '</div>' + 
      '</div>' + 
    '</div>');
});

//预览大图，模态框
angular.module("template/modal/imageDialog.html", []).run(function($templateCache) {
  $templateCache.put("template/modal/imageDialog.html",
    '<div class="img-dialog" ng-hide="closed">'+
      '<div class="img-header">'+
        '<button type="button" class="closeBtn" ng-click="closeDialog()">&times;</button>'+ 
      '</div>'+        
      '<div class="img-body">'+          
        '<div class="img-wrap">'+            
          '<img ng-src="{{img.link}}" border="0" id="view-image" ng-show="img.loaded"/>'+          
        '</div>'+          
        '<div class="img-nav">' +           
          '<div class="img-nav-prev" ng-click="prev()" ng-mouseenter="hover()" ng-mouseleave="hover()" ng-show="hasPrev()"><span class="nav-prev"><i class="fa fa-angle-left"></i></span></div>'+            
          '<div class="img-nav-next" ng-click="next()" ng-mouseenter="hover()" ng-mouseleave="hover()" ng-show="hasNext()"><span class="nav-next" ><i class="fa fa-angle-right"></i></span></div>'+          
        '</div>'+          
        '<div class="img-loader" id="img-loader"></div>'+      
      '</div>'+        
      '<div class="img-sidebar">'+          
        '<div class="box">' +           
          '<ul class="file-info">'+
            '<li class="title" ng-bind="img.title"></li>'+
            '<li ng-show="img.directory">所属文件夹： <span ng-bind="img.directory"></span></li>'+
            '<li ng-show="img.createdAt">拍摄日期：<span ng-bind="img.createdAt"></span></li>'+
          '</ul>'+            
          '<div class="splitter"></div> '+          
        '</div>'+        
      '</div>'+      
    '</div>');
});

//侧条栏
angular.module("template/common/sidebar.html", []).run(function($templateCache) {
  $templateCache.put("template/common/sidebar.html",
    '<div id="scrollSidebar" class="scrollSidebar">'+
      '<a href="javascript:void(0)" id="goTop" title="回到顶部" ng-click="goTop()"><i class="glyphicon glyphicon-menu-up"></i></a>'+
  '</div>');
});

//上传任务模态框
angular.module("template/uploadTask.html", []).run(function($templateCache){
  $templateCache.put("template/uploadTask.html", 
  '<div class="dialog dialog-blue dialog-web-uploader" id="uploadTaskDialog" role="dialog" ng-show="showDialog">'+
    '<div class="dialog-header" ng-show="!minimalDialog">'+
      '<h3>'+
        '<span class="dialog-header-title">'+
          '<em class="select-text" ng-show="uploadTask.inprocess">正在上传({{uploadTask.current}})/{{uploadTask.totalFiles}}</em>'+
          '<em class="select-text" ng-show="!uploadTask.inprocess">{{uploadTask.tips}}</em>'+
        '</span>'+
      '</h3>'+
      '<div class="dialog-control">'+
        '<span class="dialog-icon dialog-close" ng-click="closeUploadDialog()">&times;</span>'+
        '<span class="dialog-icon dialog-min" ng-click="minDialog()">-</span>'+
      '</div>'+
    '</div>'+ 
    '<div class="dialog-min-header" ng-show="minimalDialog">'+
      '<h3>'+
        '<span class="dialog-header-title">'+
          '<em class="select-text" ng-show="uploadTask.inprocess">正在上传({{uploadTask.current}})/{{uploadTask.totalFiles}}</em>'+
          '<em class="select-text" ng-show="!uploadTask.inprocess">{{uploadTask.tips}}</em>'+
        '</span>'+
      '</h3>'+
      '<div class="dialog-control">'+
        '<span class="dialog-icon dialog-close" ng-click="closeUploadDialog()">&times;</span>'+
        '<span class="dialog-icon dialog-back" ng-click="maxDialog()">□</span>'+
      '</div>'+
    '</div>'+
    '<div class="dialog-body" ng-show="!minimalDialog">'+
      '<div class="upload-list-wrapper">'+
        '<div class="uploader-list-header">'+
          '<div class="file-name">文件(夹)名</div>'+
          '<div class="file-size">大小</div>'+
          '<div class="file-status">状态</div>'+
        '</div>'+
        '<div class="uploader-list">'+
          '<ul id="uploaderList" class="wpcontainer">'+
            '<li class="file-list status-success" ng-repeat="file in uploadTask.files">'+
              '<div class="info">'+
                '<div class="file-name" title="{{file.name}}">'+
                  '<div class="file-icon fileicon-small-pic"></div>'+
                  '<span class="name-text" ng-bind="file.name"></span>'+
                '</div>'+
                '<div class="file-size">{{file.size}}B</div>'+
                '<div class="file-status">'+
                  '<span class="waiting" ng-show="file.status==\'waiting\'">排队中</span>'+
                  '<span class="prepare" ng-show="file.status==\'prepare\'">准备上传...</span>'+
                  '<span class="uploading" ng-show="file.status==\'uploading\'">'+
                    '<div class="progress progress-striped active">'+
                       '<div class="progress-bar progress-bar-info" role="progressbar" style="width: {{file.progress}}%;">'+
                          '<span class="sr-only">{{file.progress}}% 完成</span>'+
                       '</div>'+
                    '</div>'+
                  '</span>'+
                  '<span class="error" ng-show="file.status==\'error\'">'+
                    '<em></em>'+
                    '<i>服务器错误</i>'+
                  '</span>'+
                  '<span class="success" ng-show="file.status==\'success\'">'+
                    '<em></em>'+  
                    '<i></i>'+
                  '</span>'+
                '</div>'+
              '</div>'+
            '</li>'+
          '</ul>'+
        '</div>'+
      '</div>'+
    '</div>'+
  '</div>');
});

/*! angular-breadcrumb - v0.4.1
 * http://ncuillery.github.io/angular-breadcrumb
 * Copyright (c) 2015 Nicolas Cuillery; Licensed MIT 
*/
(function (window, angular, undefined) {
 'use strict';

 function isAOlderThanB(scopeA, scopeB) {
   if(angular.equals(scopeA.length, scopeB.length)) {
     return scopeA > scopeB;
   } else {
     return scopeA.length > scopeB.length;
   }
 }

 function parseStateRef(ref) {
  var parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/);
  if (!parsed || parsed.length !== 4) { throw new Error("Invalid state ref '" + ref + "'"); }
  return { state: parsed[1], paramExpr: parsed[3] || null };
 }

function $Breadcrumb() {

  var $$options = {
    prefixStateName: null,
    template: 'bootstrap3',
    templateUrl: null,
    includeAbstract : false
  };

  this.setOptions = function(options) {
    angular.extend($$options, options);
  };

  this.$get = ['$state', '$stateParams', '$rootScope', function($state, $stateParams, $rootScope) {
    var $lastViewScope = $rootScope;

    // Early catch of $viewContentLoaded event
    $rootScope.$on('$viewContentLoaded', function (event) {
       // With nested views, the event occur several times, in "wrong" order
       if(!event.targetScope.ncyBreadcrumbIgnore &&
         isAOlderThanB(event.targetScope.$id, $lastViewScope.$id)) {
         $lastViewScope = event.targetScope;
     }
    });

  // Get the parent state
  var $$parentState = function(state) {
     // Check if state has explicit parent OR we try guess parent from its name
     var parent = state.parent || (/^(.+)\.[^.]+$/.exec(state.name) || [])[1];
     var isObjectParent = typeof parent === "object";
     // if parent is a object reference, then extract the name
     return isObjectParent ? parent.name : parent;
   };

  // Add the state in the chain if not already in and if not abstract
  var $$addStateInChain = function(chain, stateRef) {
   var conf,
   parentParams,
   ref = parseStateRef(stateRef),
   force = false,
   skip = false;

   for(var i=0, l=chain.length; i<l; i+=1) {
     if (chain[i].name === ref.state) {
       return;
     }
   }

  conf = $state.get(ref.state);
  // Get breadcrumb options
  if(conf.ncyBreadcrumb) {
    if(conf.ncyBreadcrumb.force){ force = true; }
    if(conf.ncyBreadcrumb.skip){ skip = true; }
  }
  if((!conf.abstract || $$options.includeAbstract || force) && !skip) {
   if(ref.paramExpr) {
     parentParams = $lastViewScope.$eval(ref.paramExpr);
   }

   conf.ncyBreadcrumbLink = $state.href(ref.state, parentParams || $stateParams || {});
   chain.unshift(conf);
  }
};

// Get the state for the parent step in the breadcrumb
var $$breadcrumbParentState = function(stateRef) {
 var ref = parseStateRef(stateRef),
 conf = $state.get(ref.state);

 if(conf.ncyBreadcrumb && conf.ncyBreadcrumb.parent) {
       // Handle the "parent" property of the breadcrumb, override the parent/child relation of the state
       var isFunction = typeof conf.ncyBreadcrumb.parent === 'function';
       var parentStateRef = isFunction ? conf.ncyBreadcrumb.parent($lastViewScope) : conf.ncyBreadcrumb.parent;
       if(parentStateRef) {
         return parentStateRef;
       }
     }

     return $$parentState(conf);
   };

   return {

     getTemplate: function(templates) {
       if($$options.templateUrl) {
           // templateUrl takes precedence over template
           return null;
         } else if(templates[$$options.template]) {
           // Predefined templates (bootstrap, ...)
           return templates[$$options.template];
         } else {
           return $$options.template;
         }
       },

       getTemplateUrl: function() {
         return $$options.templateUrl;
       },

   getStatesChain: function(exitOnFirst) { // Deliberately undocumented param, see getLastStep
     var chain = [];

       // From current state to the root
       for(var stateRef = $state.$current.self.name; stateRef; stateRef=$$breadcrumbParentState(stateRef)) {
         $$addStateInChain(chain, stateRef);
         if(exitOnFirst && chain.length) {
           return chain;
         }
       }

       // Prefix state treatment
       if($$options.prefixStateName) {
         $$addStateInChain(chain, $$options.prefixStateName);
       }

       return chain;
     },

     getLastStep: function() {
       var chain = this.getStatesChain(true);
       return chain.length ? chain[0] : undefined;
     },

     $getLastViewScope: function() {
       return $lastViewScope;
     }
   };
 }];
}

var getExpression = function(interpolationFunction) {
 if(interpolationFunction.expressions) {
   return interpolationFunction.expressions;
 } else {
   var expressions = [];
   angular.forEach(interpolationFunction.parts, function(part) {
     if(angular.isFunction(part)) {
       expressions.push(part.exp);
     }
   });
   return expressions;
 }
};

var registerWatchers = function(labelWatcherArray, interpolationFunction, viewScope, step) {
 angular.forEach(getExpression(interpolationFunction), function(expression) {
   var watcher = viewScope.$watch(expression, function() {
     step.ncyBreadcrumbLabel = interpolationFunction(viewScope);
   });
   labelWatcherArray.push(watcher);
 });

};

var deregisterWatchers = function(labelWatcherArray) {
 angular.forEach(labelWatcherArray, function(deregisterWatch) {
   deregisterWatch();
 });
};

function BreadcrumbDirective($interpolate, $breadcrumb, $rootScope) {
 var $$templates = {
   bootstrap2: '<ul class="breadcrumb">' +
   '<li ng-repeat="step in steps" ng-switch="$last || !!step.abstract" ng-class="{active: $last}">' +
   '<a ng-switch-when="false" href="{{step.ncyBreadcrumbLink}}">{{step.ncyBreadcrumbLabel}}</a>' +
   '<span ng-switch-when="true">{{step.ncyBreadcrumbLabel}}</span>' +
   '<span class="divider" ng-hide="$last">/</span>' +
   '</li>' +
   '</ul>',
   bootstrap3: '<ol class="breadcrumb">' +
   '<li ng-repeat="step in steps" ng-class="{active: $last}" ng-switch="$last || !!step.abstract">' +
   '<a ng-switch-when="false" href="{{step.ncyBreadcrumbLink}}"><i ng-if="step.ncyBreadcrumb.icon" class="{{step.ncyBreadcrumb.icon}}"></i> {{step.ncyBreadcrumbLabel}}</a>' +
   '<span ng-switch-when="true"><i ng-if="step.ncyBreadcrumb.icon" class="{{step.ncyBreadcrumb.icon}}"></i> {{step.ncyBreadcrumbLabel}}</span>' +
   '</li>' +
   '</ol>'
 };

 return {
   restrict: 'AE',
   replace: true,
   scope: {},
   template: $breadcrumb.getTemplate($$templates),
   templateUrl: $breadcrumb.getTemplateUrl(),
   link: {
     post: function postLink(scope) {
       var labelWatchers = [];

       var renderBreadcrumb = function() {
         deregisterWatchers(labelWatchers);
         labelWatchers = [];
         
         var viewScope = $breadcrumb.$getLastViewScope();
         scope.steps = $breadcrumb.getStatesChain();
         angular.forEach(scope.steps, function (step) {
           if (step.ncyBreadcrumb && step.ncyBreadcrumb.label) {
             var parseLabel = $interpolate(step.ncyBreadcrumb.label);
             step.ncyBreadcrumbLabel = parseLabel(viewScope);
                   // Watcher for further viewScope updates
                   registerWatchers(labelWatchers, parseLabel, viewScope, step);
                 } else {
                   step.ncyBreadcrumbLabel = step.name;
                 }
               });
       };

       $rootScope.$on('$viewContentLoaded', function (event) {
         if(!event.targetScope.ncyBreadcrumbIgnore) {
           renderBreadcrumb();
         }
       });

       // View(s) may be already loaded while the directive's linking
       renderBreadcrumb();
     }
   }
 };
}
BreadcrumbDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope'];

function BreadcrumbLastDirective($interpolate, $breadcrumb, $rootScope) {

 return {
   restrict: 'A',
   scope: {},
   template: '{{ncyBreadcrumbLabel}}',
   compile: function(cElement, cAttrs) {

   // Override the default template if ncyBreadcrumbLast has a value
   var template = cElement.attr(cAttrs.$attr.ncyBreadcrumbLast);
   if(template) {
     cElement.html(template);
   }

   return {
     post: function postLink(scope) {
       var labelWatchers = [];

       var renderLabel = function() {
         deregisterWatchers(labelWatchers);
         labelWatchers = [];

         var viewScope = $breadcrumb.$getLastViewScope();
         var lastStep = $breadcrumb.getLastStep();
         if(lastStep) {
           scope.ncyBreadcrumbLink = lastStep.ncyBreadcrumbLink;
           if (lastStep.ncyBreadcrumb && lastStep.ncyBreadcrumb.label) {
             var parseLabel = $interpolate(lastStep.ncyBreadcrumb.label);
             scope.ncyBreadcrumbLabel = parseLabel(viewScope);
                       // Watcher for further viewScope updates
                       // Tricky last arg: the last step is the entire scope of the directive !
                       registerWatchers(labelWatchers, parseLabel, viewScope, scope);
                     } else {
                       scope.ncyBreadcrumbLabel = lastStep.name;
                     }
                   }
                 };

                 $rootScope.$on('$viewContentLoaded', function (event) {
                   if(!event.targetScope.ncyBreadcrumbIgnore) {
                     renderLabel();
                   }
                 });

           // View(s) may be already loaded while the directive's linking
           renderLabel();
         }
       };

     }
   };
 }
 BreadcrumbLastDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope'];

 function BreadcrumbTextDirective($interpolate, $breadcrumb, $rootScope) {

   return {
     restrict: 'A',
     scope: {},
     template: '{{ncyBreadcrumbChain}}',

     compile: function(cElement, cAttrs) {
   // Override the default template if ncyBreadcrumbText has a value
   var template = cElement.attr(cAttrs.$attr.ncyBreadcrumbText);
   if(template) {
     cElement.html(template);
   }

   var separator = cElement.attr(cAttrs.$attr.ncyBreadcrumbTextSeparator) || ' / ';

   return {
     post: function postLink(scope) {
       var labelWatchers = [];

       var registerWatchersText = function(labelWatcherArray, interpolationFunction, viewScope) {
         angular.forEach(getExpression(interpolationFunction), function(expression) {
           var watcher = viewScope.$watch(expression, function(newValue, oldValue) {
             if (newValue !== oldValue) {
               renderLabel();
             }
           });
           labelWatcherArray.push(watcher);
         });
       };

       var renderLabel = function() {
         deregisterWatchers(labelWatchers);
         labelWatchers = [];

         var viewScope = $breadcrumb.$getLastViewScope();
         var steps = $breadcrumb.getStatesChain();
         var combinedLabels = [];
         angular.forEach(steps, function (step) {
           if (step.ncyBreadcrumb && step.ncyBreadcrumb.label) {
             var parseLabel = $interpolate(step.ncyBreadcrumb.label);
             combinedLabels.push(parseLabel(viewScope));
                       // Watcher for further viewScope updates
                       registerWatchersText(labelWatchers, parseLabel, viewScope);
                     } else {
                       combinedLabels.push(step.name);
                     }
                   });

         scope.ncyBreadcrumbChain = combinedLabels.join(separator);
       };

       $rootScope.$on('$viewContentLoaded', function (event) {
         if(!event.targetScope.ncyBreadcrumbIgnore) {
           renderLabel();
         }
       });

           // View(s) may be already loaded while the directive's linking
           renderLabel();
         }
       };

     }
   };
 }
 BreadcrumbTextDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope'];

 angular.module('ncy-angular-breadcrumb', ['ui.router.state'])
 .provider('$breadcrumb', $Breadcrumb)
 .directive('ncyBreadcrumb', BreadcrumbDirective)
 .directive('ncyBreadcrumbLast', BreadcrumbLastDirective)
 .directive('ncyBreadcrumbText', BreadcrumbTextDirective);
})(window, window.angular);

(function(){
  var Yihu = {};
  Yihu.version = "1.0";
  window.Yihu = Yihu;

  /** 通用工具类 */
  var util = Yihu.util = {
    //替换成图片延迟HTML
    replaceLazyHtml : function(html){
      if(!html){
        return '';
      }
      var regex = new RegExp("(img src=\")(\\S)*(\")","g"); 
      var array = html.match(regex); 
      if(!array){
        return html;
      }

      for(var i=0; i<array.length;i++){
        var str = array[i]; 
        var src = str.substring(str.indexOf("src")+5, str.length-1);
        html = html.replace(str, 'img class="lazy" data-original="'+src+'" src=""') ;
      }
      return html;
    },

    restoreRawHtml : function(html){
      if(!html){
        return '';
      }
      var regex = new RegExp("(img class=\"lazy\" data-original=\")(\\S)*(\")","g"); 
      var array = html.match(regex); 
      if(!array){
        return html;
      }
      for(var i=0; i<array.length;i++){
        var str = array[i]; 
        var src = str.substring(str.indexOf("data-original")+"data-original".length+2, str.length-1);
        html = html.replace('src=""', '').replace(str, 'img src="'+src+'"');
      }
      return html;
    },

    setContext : function(ctx, url){
      if(url && url.indexOf("?")>=0){
        var search = url.substring(url.indexOf('?')+1).replace('?','&');
        var pairs = search.split('&');
        var uniqueParams = [];
        var finalPairs = [];

        for(var i=0; i<pairs.length; i++){
          var parameter = pairs[i].split('=');
          if(parameter.length == 2 && uniqueParams.indexOf(parameter[0]) == -1){
            uniqueParams.push(parameter[0]);
            finalPairs.push(pairs[i]);
          }else if(parameter.length < 2){
            finalPairs.push(pairs[i]);
          }
        }
        var prefix = url.substring(0, url.indexOf('?')+1);
        url = prefix + finalPairs.join('&');
      }
      return  (url && url.indexOf(ctx)==-1) ? ctx+url : url;
    }
  };

  /**
   * Cookie工具类
   */
  var cookie = Yihu.Cookie = {
    add : function(name, value, expires, path){
      var opts = {
        name:name||'',
        value:value||'',
        expires:isNaN(expires) ? 0 : expires,
        path:path||'/'
      };

      var exp = new Date();
      exp.setTime(exp.getTime() + opts.expires);
      document.cookie = opts.name + 
        "=" + escape(opts.value) + 
        ";expires=" + exp.toGMTString() + 
        ";path=" + opts.path;
    },

    get : function(name){
      var arr = document.cookie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"));
      if(arr) {
        return unescape(arr[2]);
      }
      return null;
    },

    remove : function(name, path){
      var opts = {
        name:name||'',
        path:path||'/'
      };

      var exp = new Date();
      exp.setTime(exp.getTime() - 1000);    
      document.cookie = opts.name + 
        "=;expires=" + exp.toGMTString() + 
        ";path=" + opts.path;
    }
  };
})();